
#include "fiber.h"

#include <stdlib.h>
#include "fiber-env.h"

namespace dulymoo {

Fiber::Fiber() :
    need_recycle_(false), func_(0), arg_(0)
{
    getcontext(&context_);
}

Fiber::Fiber(void (*func)(void*), void* arg, unsigned long stack_size) :
    need_recycle_(true), func_(func), arg_(arg)
{
    if (stack_size == 0)
        stack_size = 1024*1024;

    getcontext(&context_);
    context_.uc_stack.ss_sp = (void*)(new char[stack_size]);
    context_.uc_stack.ss_size = stack_size;
    makecontext(&context_, (void (*)())FiberProc, 1, this);
}

Fiber::~Fiber()
{
    if (need_recycle_)
    {
        char* stack = reinterpret_cast<char*>(context_.uc_stack.ss_sp);
        delete []stack;
    }
}

bool Fiber::SwitchTo(Fiber &from)
{
    return 0 == swapcontext(&from.context_, &context_);
}

bool Fiber::SwitchTo()
{
    return 0 == setcontext(&context_);
}

void Fiber::FiberProc(void* arg)
{
    Fiber* fiber = reinterpret_cast<Fiber*>(arg);
    if (fiber != NULL)
        (fiber->func_)(fiber->arg_);
    FiberEnv::Quit();
}

} // namespace dulymoo

